When limited physical pins are available (e.g., only 4 input data pins), we can use a register file to store multiple 4-bit values and perform a 16-bit + 16-bit addition by combining them into two 16-bit operands.
In this design:
- Eight 4-bit registers are used.
- Registers
regfile[0]–regfile[3]form the first 16-bit operand (A). - Registers
regfile[4]–regfile[7]form the second 16-bit operand (B). - A 3-to-8 decoder selects which register to write to based on the 3-bit address.
- The result of the addition is displayed on four seven-segment displays.
Block Diagram

Verilog Implementation
16-Bit Ripple Carry Adder
module add16(
input Cin,
input [15:0] A, B,
output Cout,
output [15:0] S
);
wire RCA4_Cout0, RCA4_Cout1, RCA4_Cout2;
wire [3:0] S_0, S_1, S_2, S_3;
RCA4 RCA4_0(.A(A[3:0]), .B(B[3:0]), .C_in(Cin), .Sum(S_0), .C_out(RCA4_Cout0));
RCA4 RCA4_1(.A(A[7:4]), .B(B[7:4]), .C_in(RCA4_Cout0), .Sum(S_1), .C_out(RCA4_Cout1));
RCA4 RCA4_2(.A(A[11:8]), .B(B[11:8]), .C_in(RCA4_Cout1), .Sum(S_2), .C_out(RCA4_Cout2));
RCA4 RCA4_3(.A(A[15:12]), .B(B[15:12]), .C_in(RCA4_Cout2), .Sum(S_3), .C_out(Cout));
assign S = {S_3, S_2, S_1, S_0};
endmodule
Register File + 16-Bit Adder
module Reg_Add16(
input reset, RW, clk,
input [3:0] Din,
input [2:0] addr,
output add_cout,
output [15:0] add_sout,
output [3:0] read_value
);
wire [7:0] Decoder_out;
wire [7:0] reg_en;
reg [3:0] regfile[0:7];
// Address Decoder
Decoder3to8 Decoder0(.Din(addr), .Dout(Decoder_out));
assign reg_en = (RW) ? 8'd0 : Decoder_out;
// Register write logic
always @(posedge clk or negedge reset) begin
if (!reset) begin
regfile[0] <= 4'd0;
regfile[1] <= 4'd0;
regfile[2] <= 4'd0;
regfile[3] <= 4'd0;
regfile[4] <= 4'd0;
regfile[5] <= 4'd0;
regfile[6] <= 4'd0;
regfile[7] <= 4'd0;
end
else begin
regfile[0] <= (reg_en[0]) ? Din : regfile[0];
regfile[1] <= (reg_en[1]) ? Din : regfile[1];
regfile[2] <= (reg_en[2]) ? Din : regfile[2];
regfile[3] <= (reg_en[3]) ? Din : regfile[3];
regfile[4] <= (reg_en[4]) ? Din : regfile[4];
regfile[5] <= (reg_en[5]) ? Din : regfile[5];
regfile[6] <= (reg_en[6]) ? Din : regfile[6];
regfile[7] <= (reg_en[7]) ? Din : regfile[7];
end
end
// Concatenate 4-bit registers into 16-bit inputs
wire [15:0] add_in_A = {regfile[3], regfile[2], regfile[1], regfile[0]};
wire [15:0] add_in_B = {regfile[7], regfile[6], regfile[5], regfile[4]};
// 16-bit adder instance
add16 add16_0(.A(add_in_A), .B(add_in_B), .S(add_sout), .Cin(1'b0), .Cout(add_cout));
// Read selected register
assign read_value = regfile[addr];
endmodule
Integration with Debounce Button & Seven-Segment Display
module RA16_display(
input reset, btn, clk, RW,
input [2:0] addr,
input [3:0] data,
output add_cout,
output [3:0] Sout0, Sout1, Sout2, Sout3, read_value
);
wire DC_clk;
wire [15:0] add_result;
// Debounce Button (generates clean clock pulse)
Debounce_Circuit DC0(.Din(btn), .clk(clk), .reset(reset), .Dout(DC_clk));
// Register + Adder
Reg_Add16 RA16(
.reset(reset),
.Din(data),
.addr(addr),
.RW(RW),
.clk(DC_clk), // <--- use debounced button as clock
.add_sout(add_result),
.add_cout(add_cout),
.read_value(read_value)
);
// Display output on four 7-segment displays
Seven_Segment SS0(.Din(add_result[3:0]), .Dout(Sout0));
Seven_Segment SS1(.Din(add_result[7:4]), .Dout(Sout1));
Seven_Segment SS2(.Din(add_result[11:8]), .Dout(Sout2));
Seven_Segment SS3(.Din(add_result[15:12]), .Dout(Sout3));
endmodule